package com.example.wenhua.service.impl;

import com.example.wenhua.service.SqlGeneratorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

/**
 * SQL生成服务实现类
 */
@Slf4j
@Service
public class SqlGeneratorServiceImpl implements SqlGeneratorService {
    
    // 危险SQL关键词黑名单
    private static final List<String> DANGEROUS_KEYWORDS = Arrays.asList(
        "DROP", "DELETE", "UPDATE", "INSERT", "ALTER", "CREATE", "TRUNCATE",
        "EXEC", "EXECUTE", "UNION", "--", "/*", "*/", "SCRIPT",
        "DECLARE", "CURSOR", "PROCEDURE", "FUNCTION"
    );
    
    // 允许的表名白名单
    private static final List<String> ALLOWED_TABLES = Arrays.asList(
        "s", "c", "sc", "user"
    );
    
    @Override
    public boolean validateSqlSafety(String sql) {
        if (sql == null || sql.trim().isEmpty()) {
            return false;
        }
        
        String upperSql = sql.toUpperCase().trim();
        
        // 检查是否为SELECT查询
        if (!isSelectQuery(sql)) {
            log.warn("非SELECT查询被拒绝: {}", sql);
            return false;
        }
        
        // 检查危险关键词
        for (String keyword : DANGEROUS_KEYWORDS) {
            if (upperSql.contains(keyword)) {
                log.warn("包含危险关键词 '{}' 的SQL被拒绝: {}", keyword, sql);
                return false;
            }
        }
        
        // 检查是否包含多个语句（分号分隔）
        // 允许SQL语句末尾的单个分号，但拒绝多个完整语句
        String trimmedSql = sql.trim();
        if (trimmedSql.contains(";")) {
            // 如果分号不在末尾，或者有多个分号，则拒绝
            if (!trimmedSql.endsWith(";") || trimmedSql.indexOf(";") != trimmedSql.lastIndexOf(";")) {
                log.warn("包含多个语句或分号位置不当的SQL被拒绝: {}", sql);
                return false;
            }
        }
        
        // 检查表名是否在白名单中
        if (!validateTableNames(sql)) {
            log.warn("包含非法表名的SQL被拒绝: {}", sql);
            return false;
        }
        
        return true;
    }
    
    @Override
    public String sanitizeSql(String sql) {
        if (sql == null) {
            return null;
        }
        
        // 移除多余的空格和换行符
        sql = sql.trim().replaceAll("\\s+", " ");
        
        // 移除末尾的分号
        if (sql.endsWith(";")) {
            sql = sql.substring(0, sql.length() - 1);
        }
        
        // 移除SQL注释
        sql = sql.replaceAll("--.*$", "").replaceAll("/\\*.*?\\*/", "");
        
        return sql.trim();
    }
    
    @Override
    public boolean isSelectQuery(String sql) {
        if (sql == null || sql.trim().isEmpty()) {
            return false;
        }
        
        String trimmedSql = sql.trim().toUpperCase();
        return trimmedSql.startsWith("SELECT");
    }
    
    @Override
    public String addRoleBasedRestrictions(String sql, Integer userRole, String userId) {
        if (sql == null || userRole == null) {
            return sql;
        }
        
        String upperSql = sql.toUpperCase();
        
        // 管理员(role=0)：无限制
        if (userRole == 0) {
            return sql;
        }
        
        // 教师(role=1)：可以查看所有数据，但不能查看用户密码
        if (userRole == 1) {
            // 如果查询用户表，排除密码字段
            if (upperSql.contains("FROM USER") || upperSql.contains("JOIN USER")) {
                sql = sql.replaceAll("(?i)SELECT \\*", "SELECT hm, role");
                if (upperSql.contains("SELECT PWD") || upperSql.contains(", PWD")) {
                    sql = sql.replaceAll("(?i), ?pwd", "").replaceAll("(?i)pwd,?", "");
                }
            }
            return sql;
        }
        
        // 学生(role=2)：只能查看自己的相关数据
        if (userRole == 2) {
            // 如果查询学生表，只能查看自己的信息
            if (upperSql.contains("FROM S") && !upperSql.contains("WHERE")) {
                sql += " WHERE sno = '" + userId + "'";
            } else if (upperSql.contains("FROM S") && upperSql.contains("WHERE")) {
                sql += " AND sno = '" + userId + "'";
            }
            
            // 如果查询选课表，只能查看自己的选课
            if (upperSql.contains("FROM SC") && !upperSql.contains("WHERE")) {
                sql += " WHERE sno = '" + userId + "'";
            } else if (upperSql.contains("FROM SC") && upperSql.contains("WHERE")) {
                sql += " AND sc.sno = '" + userId + "'";
            }
            
            // 禁止查询用户表
            if (upperSql.contains("FROM USER") || upperSql.contains("JOIN USER")) {
                throw new SecurityException("学生用户无权查询用户表");
            }
        }
        
        return sql;
    }
    
    /**
     * 验证SQL中的表名是否在白名单中
     */
    private boolean validateTableNames(String sql) {
        String upperSql = sql.toUpperCase();
        
        // 简单的表名提取（可以根据需要改进）
        Pattern tablePattern = Pattern.compile("FROM\\s+(\\w+)|JOIN\\s+(\\w+)");
        java.util.regex.Matcher matcher = tablePattern.matcher(upperSql);
        
        while (matcher.find()) {
            String tableName = matcher.group(1) != null ? matcher.group(1) : matcher.group(2);
            if (!ALLOWED_TABLES.contains(tableName.toLowerCase())) {
                return false;
            }
        }
        
        return true;
    }
}